﻿using System;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections.Generic;
using System.ComponentModel;
using System.Collections.ObjectModel;
using System.ComponentModel.Composition;
using Caliburn.Micro.BikeWizard.Data;
using Caliburn.Micro.BikeWizard.Validation;
using Caliburn.Micro.BikeWizard.Services;
using Caliburn.Micro.BikeWizard.Utils;

namespace Caliburn.Micro.BikeWizard.Views
{
    public class BikeTypeFrameSizeViewModel : Screen, IValidatable
    {
        #region Private Properties (Services)
        private IBikeOptionService bikeOptionService { get; set; }
        private IEventAggregator eventAggregator { get; set; }
        #endregion

        #region Internal Properties (Data)
        internal BikeOrder bikeOrder { get; set; }

        internal FrameSizeOption SelectedFrameSize
        {
            get
            {
                return bikeOrder.FrameSize;
            }
            set
            {
                bikeOrder.FrameSize = value;
                NotifyOfPropertyChange(() => this.IsValid);
            }
        }

        internal BikeTypeOption SelectedBikeType
        {
            get
            {
                return bikeOrder.BikeType;
            }
            set
            {
                bikeOrder.BikeType = value;
                NotifyOfPropertyChange(() => this.IsValid);
            }
        }
        #endregion

        #region Public Properties (Bindable)
        public ReadOnlyCollection<OptionViewModel<FrameSizeOption>> AvailableFrameSizes { get; private set; }
        public ReadOnlyCollection<OptionViewModel<BikeTypeOption>> AvailableBikeTypes { get; private set; }
        #endregion

        #region IValidatable Implementation
        public bool IsValid
        {
            get
            {
                return this.bikeOrder.BikeType != null && this.bikeOrder.FrameSize != null;
            }
        }
        #endregion

        #region Constructors
        public BikeTypeFrameSizeViewModel(
            IEventAggregator eventAggregator,
            IBikeOptionService bikeOptionService,
            BikeOrder bikeOrder)
        {
            this.eventAggregator = eventAggregator;
            this.bikeOptionService = bikeOptionService;

            this.DisplayName = "Type & frame size";
            this.bikeOrder = bikeOrder;

            new CoroutineExecutor(GetAndCreateOptions()).Execute(null);
        }
        #endregion

        #region Private Methods
        private IEnumerable<IResult> GetAndCreateOptions()
        {
            yield return bikeOptionService.GetAvailableBikeTypes();
            yield return OptionViewModelHelper.CreateOptionViewModelList<BikeTypeOption>(
                bikeOptionService.BikeTypes,
                (result) => this.AvailableBikeTypes = new ReadOnlyCollection<OptionViewModel<BikeTypeOption>>(result.ToList()),
                (defaultBikeType) => this.SelectedBikeType = defaultBikeType.GetValue(),
                (selectedBikeType) => this.SelectedBikeType = selectedBikeType.GetValue());
            yield return bikeOptionService.GetAvailableFrameSizes();
            yield return OptionViewModelHelper.CreateOptionViewModelList<FrameSizeOption>(
                bikeOptionService.FrameSizes,
                (result) => this.AvailableFrameSizes = new ReadOnlyCollection<OptionViewModel<FrameSizeOption>>(result.ToList()),
                (defaultFrameSize) => this.SelectedFrameSize = defaultFrameSize.GetValue(),
                (selectedFrameSize) => this.SelectedFrameSize = selectedFrameSize.GetValue());
        }
        #endregion
    }
}
